import jinja2
import http.server as server
import shutil, os, sys

import copy
import datetime
import email.utils
import html
import http.client
import io
import mimetypes
import posixpath
import select
import sys
import time
import urllib.parse
import contextlib
from functools import partial

from http import HTTPStatus
# 这份代码会创造一个小服务器，用模板文件去实时渲染
# 不建议在真正的生产环境中使用

env = jinja2.Environment(loader=jinja2.FileSystemLoader(searchpath='templates'))
def RenderToFile(templateName,outputPath):
	print('Re-rendering',templateName,end=' ',flush=True)
	renderResult = env.get_template(templateName).render()
	print('Finished')
	with open(outputPath,'w') as f:
		f.write(renderResult)

class MyHTTPRequestHandler(server.SimpleHTTPRequestHandler):

	def send_head(self):
		"""Common code for GET and HEAD commands.
		This sends the response code and MIME headers.
		Return value is either a file object (which has to be copied
		to the outputfile by the caller unless the command was HEAD,
		and must be closed by the caller under all circumstances), or
		None, in which case the caller has nothing further to do.
		"""
		path = self.translate_path(self.path)

		f = None
		if os.path.isdir(path):
			parts = urllib.parse.urlsplit(self.path)
			if not parts.path.endswith('/'):
				# redirect browser - doing basically what apache does
				self.send_response(HTTPStatus.MOVED_PERMANENTLY)
				new_parts = (parts[0], parts[1], parts[2] + '/',
							 parts[3], parts[4])
				new_url = urllib.parse.urlunsplit(new_parts)
				self.send_header("Location", new_url)
				self.end_headers()
				return None
			path = os.path.join(path,'index.html')

		ctype = self.guess_type(path)
		try:
			if ctype == 'text/html':
				filename = os.path.basename(path)
				templatePath = os.path.join(os.path.dirname(path),'templates',filename)
				RenderToFile(filename,path)
			f = open(path, 'rb')
		except OSError:
			self.send_error(HTTPStatus.NOT_FOUND, "File not found")
			return None

		try:
			fs = os.fstat(f.fileno())
			# Use browser cache if possible
			if ("If-Modified-Since" in self.headers
					and "If-None-Match" not in self.headers):
				# compare If-Modified-Since and time of last file modification
				try:
					ims = email.utils.parsedate_to_datetime(
						self.headers["If-Modified-Since"])
				except (TypeError, IndexError, OverflowError, ValueError):
					# ignore ill-formed values
					pass
				else:
					if ims.tzinfo is None:
						# obsolete format with no timezone, cf.
						# https://tools.ietf.org/html/rfc7231#section-7.1.1.1
						ims = ims.replace(tzinfo=datetime.timezone.utc)
					if ims.tzinfo is datetime.timezone.utc:
						# compare to UTC datetime of last modification
						last_modif = datetime.datetime.fromtimestamp(
							fs.st_mtime, datetime.timezone.utc)
						# remove microseconds, like in If-Modified-Since
						last_modif = last_modif.replace(microsecond=0)

						if last_modif <= ims:
							self.send_response(HTTPStatus.NOT_MODIFIED)
							self.end_headers()
							f.close()
							return None

			self.send_response(HTTPStatus.OK)
			self.send_header("Content-type", ctype)
			self.send_header("Content-Length", str(fs[6]))
			self.send_header("Last-Modified",
				self.date_time_string(fs.st_mtime))
			self.end_headers()
			return f
		except:
			f.close()
			raise

httpd = server.ThreadingHTTPServer(('0.0.0.0',8080),MyHTTPRequestHandler)
httpd.serve_forever()
